package me.leon.ext.android

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.os.Build
import android.text.TextUtils
import android.util.Log
import java.util.*
import me.leon.ext.Utils

/**
 * <pre> author: Blankj blog : http://blankj.com time : 2019/06/20 desc : utils about language
 * </pre> *
 */
object LanguageUtils {

    private const val KEY_LOCALE = "KEY_LOCALE"
    private const val VALUE_FOLLOW_SYSTEM = "VALUE_FOLLOW_SYSTEM"

    /**
     * Apply the system language.
     *
     * @param activityClassName The full class name of activity will be started after apply system
     * language.
     */
    fun applySystemLanguage(activityClassName: String) {
        applyLanguage(activityClassName, Resources.getSystem().locale(), true)
    }

    @JvmOverloads
    private fun applyLanguage(
        activityClz: Class<out Activity>?,
        locale: Locale = Resources.getSystem().locale(),
        isFollowSystem: Boolean = false
    ) {
        if (activityClz == null) {
            applyLanguage("", locale, isFollowSystem)
            return
        }
        applyLanguage(activityClz.name, locale, isFollowSystem)
    }

    @JvmOverloads
    fun applyLanguage(
        activityClassName: String,
        locale: Locale = Resources.getSystem().locale(),
        isFollowSystem: Boolean = false
    ) {
        if (isFollowSystem) {
            Utils.spUtils4Utils.put(KEY_LOCALE, VALUE_FOLLOW_SYSTEM)
        } else {
            val localLanguage = locale.language
            val localCountry = locale.country
            Utils.spUtils4Utils.put(KEY_LOCALE, "$localLanguage$$localCountry")
        }
        updateLanguage(Utils.app, locale)

        val intent = Intent()
        val realActivityClassName =
            if (TextUtils.isEmpty(activityClassName)) launcherActivity else activityClassName
        intent.component = ComponentName(Utils.app, realActivityClassName)
        intent.addFlags(
            Intent.FLAG_ACTIVITY_NEW_TASK or
                Intent.FLAG_ACTIVITY_CLEAR_TOP or
                Intent.FLAG_ACTIVITY_CLEAR_TASK
        )
        Utils.app.startActivity(intent)
    }

    internal fun applyLanguage(activity: Activity) {
        val spLocale = Utils.spUtils4Utils.getString(KEY_LOCALE)
        if (TextUtils.isEmpty(spLocale)) {
            return
        }

        if (VALUE_FOLLOW_SYSTEM == spLocale) {
            val sysLocale = Resources.getSystem().locale()
            updateLanguage(Utils.app, sysLocale)
            updateLanguage(activity, sysLocale)
            return
        }

        val languageCountry =
            spLocale!!.split("\\$".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
        if (languageCountry.size != 2) {
            Log.e("LanguageUtils", "The string of $spLocale is not in the correct format.")
            return
        }

        val settingLocale = Locale(languageCountry[0], languageCountry[1])
        updateLanguage(Utils.app, settingLocale)
        updateLanguage(activity, settingLocale)
    }

    private fun updateLanguage(context: Context, locale: Locale) {
        val resources = context.resources
        val config = resources.configuration
        val contextLocale = resources.locale()
        if (contextLocale.language == locale.language && contextLocale.country == locale.country) {
            return
        }
        val dm = resources.displayMetrics

        config.setLocale(locale)
        context.createConfigurationContext(config)

        resources.updateConfiguration(config, dm)
    }

    private val launcherActivity: String
        get() {
            val intent = Intent(Intent.ACTION_MAIN, null)
            intent.addCategory(Intent.CATEGORY_LAUNCHER)
            intent.setPackage(Utils.app.packageName)
            val pm = Utils.app.packageManager
            val info = pm.queryIntentActivities(intent, 0)
            val next = info.iterator().next()
            return if (next != null) next.activityInfo.name else "no launcher activity"
        }
}

fun Resources.locale() =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        this.configuration.locales[0]
    } else {
        this.configuration.locale
    }
